package com.vision.core.cl.ui;

import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceChangeEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.core.client.Style.SelectionMode;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.IconProvider;
import com.sencha.gxt.data.shared.ModelKeyProvider;
import com.sencha.gxt.data.shared.TreeStore;
import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent;
import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent.SelectionChangedHandler;
import com.sencha.gxt.widget.core.client.tree.Tree;
import com.vision.core.cl.AppPlace;
import com.vision.core.cl.Callback;
import com.vision.core.cl.Services;
import com.vision.core.cl.resource.CoreResources;
import com.vision.core.cm.data.TaskNode;
import com.vision.core.cm.serv.rpc.MenuService;
import com.vision.core.cm.serv.rpc.MenuServiceAsync;

/**
 * 
 * @author Mark
 *
 */
public class MenuViewImpl extends Composite implements MenuView {
	
	interface Binder extends UiBinder<Widget, MenuViewImpl> { }

	private static final Binder binder = GWT.create(Binder.class);
	
	private Presenter presenter;
	
	/**
	 * The tree's backing store
	 */
	@UiField(provided = true)
	TreeStore<TaskNode> store = new TreeStore<TaskNode>(new KeyProvider());

	/**
	 * The tree.
	 */
	@UiField
	Tree<TaskNode, String> tree;
	
	/**
	 * Icon provider for the tree.
	 */
	private IconProvider<TaskNode> iconProvider;
	
	public MenuViewImpl() {
		this(null);
	}
	
	public MenuViewImpl(IconProvider<TaskNode> iconProvider) {
		this.iconProvider = iconProvider;
		
		initWidget(binder.createAndBindUi(this));
		
		// Initialize the tree
		initializeTree();

		// Load data
		Scheduler.get().scheduleDeferred(new ScheduledCommand() {
			@Override
			public void execute() {
				loadData();		
			}
		});
	}
	
	protected void initializeTree() {
		final CoreResources bundle = GWT.create(CoreResources.class);
		
//		tree.getStyle().setJointCloseIcon(bundle.plus());
//	    tree.getStyle().setJointOpenIcon(bundle.minus());
	    tree.getStyle().setNodeCloseIcon(bundle.folder());
	    tree.getStyle().setNodeOpenIcon(bundle.folderOpen());
	    
	    if (this.iconProvider != null)
			tree.setIconProvider(this.iconProvider);
	    
	    tree.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
	    
	    // Add a selection listener
	    tree.getSelectionModel().addSelectionChangedHandler(new SelectionChangedHandler<TaskNode>() {
	    	@Override
	    	public void onSelectionChanged(SelectionChangedEvent<TaskNode> e) {
	    		List<TaskNode> nodes = e.getSelection();
				if (!nodes.isEmpty()) {
					TaskNode node = nodes.get(0);
					if (node.getChildren() == null || node.getChildren().isEmpty())
						presenter.goTo(new AppPlace(node.getId()));
				}
	    	}
		});
	}
	
	protected void loadData() {
		MenuServiceAsync service = Services.create(GWT.create(MenuService.class));
		tree.mask("Loading Tasks...");
		service.getMenu(new Callback<List<TaskNode>>(tree) {
			@Override
			protected void handleSuccess(List<TaskNode> nodes) {
				store.clear();
				
				store.add(nodes);
				for (TaskNode node : nodes) {
					List<TaskNode> children = node.getChildren();
					if (children != null) {
						store.add(node, children);
						tree.setExpanded(node, true);
					}
				}
				
			}
		});
	}
	
	protected TaskNode findNode(String id) {
		return tree.getStore().findModelWithKey(id);
	}
	
	@Override
	public void onPlaceChange(PlaceChangeEvent e) {
		Place newPlace = e.getNewPlace();
		if (newPlace instanceof AppPlace) {
			AppPlace aPlace = (AppPlace) newPlace;
			TaskNode node = findNode(aPlace.getId());
			
			if (node != null) {
				tree.setExpanded(node, true, false);
				tree.scrollIntoView(node);
				tree.getSelectionModel().select(node, false);
			} else {
				tree.getSelectionModel().deselectAll();
			}
		}
	}

	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
	}
	
	@UiFactory
	public ValueProvider<TaskNode, String> createValueProvider() {
		return new ValueProvider<TaskNode, String>() {
			@Override
			public String getValue(TaskNode object) {
				return object.getText();
			}

			@Override
			public void setValue(TaskNode object, String value) {
			}

			@Override
			public String getPath() {
				return "name";
			}
		};
	}

	// Inner classes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	static class KeyProvider implements ModelKeyProvider<TaskNode> {
		@Override
		public String getKey(TaskNode item) {
			return item.getId();
		}
	}

}
